package cqie.frame.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cqie.frame.config.MD5;
import cqie.frame.entity.*;
import cqie.frame.entity.po.SysMenuPo;
import cqie.frame.entity.po.SysUserPo;
import cqie.frame.entity.po.UserRoleMenuPo;
import cqie.frame.entity.qo.SysUserQo;
import cqie.frame.entity.vo.SysUserVo;
import cqie.frame.response.CodeMsg;
import cqie.frame.response.ResultJson;
import cqie.frame.service.*;
import io.swagger.annotations.ApiOperation;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 此表为用户表，表明用户的基本信息，如用户名称，登录账号密码，状态等。 前端控制器
 * </p>
 *
 * @author HHL
 * @since 2021-09-02
 */
@RestController
@RequestMapping("/user")
public class SysUserController {

    @Autowired
    ISysUserService iSysUserService;
    @Autowired
    IUserRoleService iUserRoleService;
    @Autowired
    ISysRoleService iSysRoleService;
    @Autowired
    IRoleMenuService iRoleMenuService;
    @Autowired
    ISysMenuService iSysMenuService;


    //新增用户
    @ApiOperation(value = "新增用户", notes = "新增用户，同时更新用户角色表。", response = SysUserPo.class)
    @PostMapping(value = "/addUser")
    public ResultJson addUser(@RequestBody SysUserPo po) {
        try {
            //构造mo
            SysUser sysUser = new SysUser();
            //复制po的属性到sysUser,第三个参数可选，为忽略某些属性
            BeanUtils.copyProperties(po, sysUser);
            //md5加密
            sysUser.setPassword(MD5.md5(sysUser.getPassword()));
            System.out.println(po.toString());
            System.out.println(sysUser.toString());
            //插入用户表后回显插入用户的主键id
            iSysUserService.save(sysUser);
            po.setId(sysUser.getId());
            //若一个用户有多个角色，批量插入用户角色表
            if (po.getRoleIdList() != null) {
                List<UserRole> userRoleList = new ArrayList<>();
                po.getRoleIdList().forEach(x -> {
                    UserRole userRole = new UserRole();
                    //设置为选中的角色id
                    userRole.setRoleId(x);
                    System.out.println(x);
                    //设置为用户表回显的用户id
                    userRole.setUserId(sysUser.getId());
                    userRoleList.add(userRole);
                });
                //插入一个list的用户角色表
                iUserRoleService.saveBatch(userRoleList);
            }
            //返回用户及其角色
            return ResultJson.success(po);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //删除选中用户，多选
    @ApiOperation(value = "删除选中用户", notes = "删除选中用户，同时更新用户角色表。")
    @PostMapping(value = "/deleteCheckUser")
    public ResultJson deleteCheckUser(@RequestBody Long[] userIdList) {
        try {
            for (int i = 0; i < userIdList.length; i++) {
                //选择器，只有UserRole的userid等同于要删除用户的id，才执行删除用户角色表
                QueryWrapper<UserRole> qw = new QueryWrapper<>();
                qw.eq("userId", userIdList[i]);
                iUserRoleService.remove(qw);
            }
            for (int i = 0; i < userIdList.length; i++) {
                //删除用户表
                iSysUserService.removeById(userIdList[i]);
            }
            return ResultJson.success("删除成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //注销/恢复选中用户，多选
    @ApiOperation(value = "注销/恢复选中用户", notes = "注销/恢复选中用户，同时更新用户表。")
    @PostMapping(value = "/disabledCheckUser")
    public ResultJson disabledCheckUser(@RequestBody Long[] userIdList) {
        try {
            for (int i = 0; i < userIdList.length; i++) {
                SysUser sysUser = new SysUser();
                //选择器，只有UserRole的userid等同于要删除用户的id，才执行删除用户角色表
                sysUser = iSysUserService.getById(userIdList[i]);
                if (sysUser.getStatus() == 0) {
                    //如果修改前为正常，修改为禁用
                    sysUser.setStatus(1);
                } else if (sysUser.getStatus() == 1) {
                    //如果修改前为禁用，修改为正常
                    sysUser.setStatus(0);
                }
                iSysUserService.updateById(sysUser);
            }
            return ResultJson.success("修改成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //删除用户
    @ApiOperation(value = "删除单个用户", notes = "删除单个用户，同时更新用户角色表。")
    @GetMapping(value = "/deleteUser")
    public ResultJson deleteUser(long id) {
        try {
            //选择器，只有UserRole的userid等同于要删除用户的id，才执行删除用户角色表
            QueryWrapper<UserRole> qw = new QueryWrapper<>();
            qw.eq("userId", id);
            iUserRoleService.remove(qw);
            //删除用户表
            iSysUserService.removeById(id);
            //返回前端
            return ResultJson.success("删除成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //注销/恢复用户
    @ApiOperation(value = "注销/恢复单个用户", notes = "注销/恢复单个用户，同时更新用户表。")
    @GetMapping(value = "/disabledUser")
    public ResultJson disabledUser(long id) {
        try {
            //选择器，只有SysUser的userid等同于要注销/恢复用户的id，才执行修改用户表
            SysUser sysUser = new SysUser();
            sysUser = iSysUserService.getById(id);
            if (sysUser.getStatus() == 0) {
                //如果状态为正常，修改为禁用
                sysUser.setStatus(1);
            } else if (sysUser.getStatus() == 1) {
                //如果状态为禁用，修改为正常
                sysUser.setStatus(0);
            }
            //修改
            iSysUserService.updateById(sysUser);
            return ResultJson.success("操作成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //修改用户
    @ApiOperation(value = "修改用户", notes = "修改用户，同时更新用户角色表。")
    @PostMapping(value = "/updateUser")
    public ResultJson updateUser(@RequestBody SysUserPo po) {
        try {
            //获取修改前的值
            SysUser olduser = iSysUserService.getById(po.getId());
            SysUser sysUser = new SysUser();
            //复制po的属性到sysUser,第三个参数可选，为忽略某些属性
            BeanUtils.copyProperties(po, sysUser);
            sysUser.setPassword(olduser.getPassword());
            //修改用户
            iSysUserService.updateById(sysUser);
            //选择器，先把所有用户角色表中等同于要修改用户的用户id删除
            QueryWrapper<UserRole> qw = new QueryWrapper<>();
            qw.eq("userId", po.getId());
            iUserRoleService.remove(qw);
            //判断修改用户时选中的角色是否为空
            if (po.getRoleIdList().size() > 0) {
                List<UserRole> userRoleList = new ArrayList<>();
                //循环把选中的角色，添加到用户角色表
                po.getRoleIdList().forEach(x -> {
                    UserRole userRole = new UserRole();
                    //userid为修改用户的id
                    userRole.setUserId(sysUser.getId());
                    //roleid为选中的角色id
                    userRole.setRoleId(x);
                    userRoleList.add(userRole);
                });
                //以list的方式重新插入用户角色表
                iUserRoleService.saveBatch(userRoleList);
            }
            return ResultJson.success("修改成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //用户条件分页查询
    @PostMapping(value = "/userListPages")
    @ApiOperation(value = "用户分页查询", response = SysUser.class)
    public ResultJson userListPages(@RequestBody SysUserQo qo) {
        try {
            //分页参数的配置
            Page<SysUser> page = new Page<>(qo.getPageIndex(), qo.getPageSize());
            //查询条件,是否输入查询条件，如姓名，账号，状态等
            //是否查询用户名
//            LambdaQueryWrapper
            QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
            if (!StringUtils.isEmpty(qo.getName())) {
                //不为空，启用查询
                //查询模糊查询
                queryWrapper.like("name", qo.getName());
            }
            //是否查询状态
            if (qo.getStatus() != null) {
                //不为空，启用查询
                queryWrapper.eq("status", qo.getStatus());
            }
            //是否查询账号
            if (!StringUtils.isEmpty(qo.getAccount())) {
                //不为空，启用查询
                //查询模糊查询
                queryWrapper.like("account", qo.getAccount());
            }
            //根据条件以及分页查询
            IPage<SysUser> resultPage = iSysUserService.page(page, queryWrapper);
            //映射查询结果
            //映射用户状态
            IPage<SysUserVo> vo = new Page<>();
            List<SysUserVo> sysUserVoList = new ArrayList<>();
            //分页数据的复制给vo
            BeanUtils.copyProperties(resultPage, vo);
            //循环把分页数据的用户状态映射
            for (SysUser mo : resultPage.getRecords()) {
                SysUserVo sysUserVo = new SysUserVo();
                BeanUtils.copyProperties(mo, sysUserVo);
                sysUserVo.setStatusShow(mo.getStatus() == 0 ? "正常" : "禁用");
                //映射用户角色
                //把分页结果的所有用户id取出
                List<Long> userIdList = resultPage.getRecords()
                        //数据流
                        .stream()
                        //映射
                        .map(x -> x.getId())
                        //去重
                        .distinct()
                        .collect(Collectors.toList());
                //取出用户角色表
                List<UserRole> userRoleLsit = new ArrayList<>();
                if (userIdList.size() > 0) {
                    QueryWrapper<UserRole> queryWrapper1 = new QueryWrapper<>();
                    queryWrapper1.in("userId", userIdList);
                    userRoleLsit = iUserRoleService.list(queryWrapper1);
                }
                //取出所有角色id
                List<Long> roleList = userRoleLsit
                        .stream()
                        //映射
                        .map(x -> x.getRoleId())
                        //去重
                        .distinct()
                        .collect(Collectors.toList());
                //取出所有角色
                List<SysRole> sysRoleList = new ArrayList<>();
                if (roleList.size() > 0) {
                    QueryWrapper<SysRole> queryWrapper2 = new QueryWrapper<>();
                    queryWrapper2.in("id", roleList);
                    sysRoleList = iSysRoleService.list(queryWrapper2);
                }
                //取出角色id
                List<Long> findRoleIdList = userRoleLsit
                        .stream()
                        .filter(x -> x.getUserId().equals(mo.getId()))
                        .map(x -> x.getRoleId())
                        .distinct()
                        .collect(Collectors.toList());
                //取出角色name
                List<String> findRoleNameList = sysRoleList
                        .stream()
                        .filter(x -> findRoleIdList.contains(x.getId()))
                        .map(x -> x.getName())
                        .distinct()
                        .collect(Collectors.toList());
                //拼接name
                sysUserVo.setRoleName(String.join("|", findRoleNameList));
                //分页新增一个用户信息
                sysUserVoList.add(sysUserVo);
            }
            //赋值给分页
            vo.setRecords(sysUserVoList);
            return ResultJson.success(vo);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

//    //查看用户详情
//    @ApiOperation(value = "查看用户详情")
//    @GetMapping("/getUser")
//    public ResultJson getUser(long id){
//        try{
//            //获取mo
//            SysUser mo = iSysUserService.getById(id);
//            //映射vo
//            SysUserVo vo = new SysUserVo();
//            BeanUtils.copyProperties(mo,vo);
//            vo.setStatusShow(mo.getStatus()==0?"正常":"禁用");
//            //隐藏密码，用*号代替
//            vo.setPassword("******");
//            //映射准备
//            QueryWrapper<SysRole> queryWrapper = new QueryWrapper();
//            //可以嵌套sql语句
//            queryWrapper.inSql("id"
//                    ,"select roleId from user_role where roleId="+id);
//            List<SysRole> findRoleIdList = iSysRoleService.list(queryWrapper);
//            vo.setRoleName(String
//                            .join("|",findRoleIdList.stream()
//                            .map(x->x.getName())
//                            .collect(Collectors.toList())));
//            //返回
//            return ResultJson.success(vo);
//        }catch (Exception e){
//            return ResultJson.error(CodeMsg.SERVER_ERROR);
//        }
//    }


    //根据用户ID进入用户的详细页面
    @ApiOperation(value = "用户详情")
    @GetMapping(value = "selectUserById")
    public ResultJson selectUserById(long id) {
        try {
            //用户角色po类
            UserRoleMenuPo userRoleMenuPo = new UserRoleMenuPo();
            //先根据用户id查到用户
            SysUser sysUser = iSysUserService.getById(id);
            //复制sysuser的属性到userRolePo,第三个参数可选，为忽略某些属性
            BeanUtils.copyProperties(sysUser, userRoleMenuPo);
            //userRolePo还差用户角色表的信息，根据用户id查询用户角色中间表
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("userId", id);
            List<UserRole> userRoleList = iUserRoleService.list(queryWrapper);
            //2.角色信息
            List<SysRole> sysRoleList = new ArrayList<>();
            //根据用户角色表查询出角色表
            userRoleList.forEach(x -> {
                SysRole sysRole = new SysRole();
                //根据用户角色表的角色id查询出角色信息
                sysRole = iSysRoleService.getById(x.getRoleId());
                sysRoleList.add(sysRole);
            });
            //把角色List插入到用户角色po类
            userRoleMenuPo.setSysRoleList(sysRoleList);
            //菜单信息
            //3.角色对应菜单信息，根据角色id查询角色菜单中间表
            List<RoleMenu> roleMenuList = new ArrayList<>();
            sysRoleList.forEach(x -> {
                QueryWrapper<RoleMenu> queryWrapper1 = new QueryWrapper();
                queryWrapper1.eq("roleId", x.getId());
                List<RoleMenu> roleMenuList1 = iRoleMenuService.list(queryWrapper1);
                roleMenuList.addAll(roleMenuList1);
            });
            //存储菜单及其子菜单
            List<SysMenuPo> menuPoList = new ArrayList<>();
            //循环找出父级菜单及其子菜单
            for (int i = 0; i < roleMenuList.size(); i++) {
                //通过角色菜单表的菜单id找出菜单表中的父级菜单
                QueryWrapper<SysMenu> queryWrapper2 = new QueryWrapper<>();
                queryWrapper2.eq("parentId", 0);
                queryWrapper2.eq("id", roleMenuList.get(i).getMenuId());
                SysMenu sysMenu = iSysMenuService.getOne(queryWrapper2);
                //如果不是父级菜单，跳出本次循环
                if (sysMenu == null) {
                    continue;
                } else {
                    //如果是父级菜单，根据父级菜单的id，找出其他子菜单的parentId为父级菜单id的菜单
                    SysMenuPo sysMenuPo = new SysMenuPo();
                    BeanUtils.copyProperties(sysMenu, sysMenuPo);
                    List<SysMenu> sysMenuList = new ArrayList<>();
                    //循环在角色菜单中找满足条件的
                    for (int j = 0; j < roleMenuList.size(); j++) {
                        //找子级菜单条件
                        QueryWrapper<SysMenu> queryWrapper3 = new QueryWrapper<>();
                        queryWrapper3.eq("parentId", sysMenu.getId());
                        queryWrapper3.eq("id", roleMenuList.get(j).getMenuId());
                        SysMenu sysMenu1 = new SysMenu();
                        sysMenu1 = iSysMenuService.getOne(queryWrapper3);
                        //如果子级菜单不是空，添加到子级菜单list
                        if (sysMenu1 != null) {
                            sysMenuList.add(sysMenu1);
                        }
                    }
                    //存放到菜单详情类
                    sysMenuPo.setChildList(sysMenuList);
                    //存放到用户角色菜单类
                    menuPoList.add(sysMenuPo);
                }
                userRoleMenuPo.setMenuList(menuPoList);
            }
            return ResultJson.success(userRoleMenuPo);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //登录
    @ApiOperation(value = "用户登录")
    @PostMapping("/login")
    public ResultJson login(@RequestBody SysUser sysUser) {
        try {
            QueryWrapper<SysUser> qw = new QueryWrapper<>();
            qw.eq("account", sysUser.getAccount());
            List<SysUser> list = iSysUserService.list(qw);
            SysUser sysUser1 = iSysUserService.getOne(qw);
            if (list.size() == 0) {
                return ResultJson.error(CodeMsg.ACCOUNT_ERROR);
            }
            boolean ifPsw = false;
            boolean ifStatus = false;
            SysUser loginUser = new SysUser();
            for (SysUser x : list) {
                //先将密码加密比较算法
                sysUser.setPassword(MD5.md5(sysUser.getPassword()));
                if (x.getPassword().equals(sysUser.getPassword())) {
                    ifPsw = true;
                    if (x.getStatus() == 0) {
                        ifStatus = true;
                        BeanUtils.copyProperties(x,loginUser);
                        break;
                    }
                }
            }
            if (ifPsw == false) {
                return ResultJson.error(CodeMsg.PSW_ERROR);
            }
            if (ifStatus == false) {
                return ResultJson.error(CodeMsg.STATUS_ERROR);
            }
            HttpServletRequest request = ((ServletRequestAttributes)
                    RequestContextHolder.getRequestAttributes())
                    .getRequest();
            HttpSession session = request.getSession();
            //屏蔽密码给前端
            loginUser.setPassword("******");
            session.setAttribute("loginUser", loginUser);
            return ResultJson.success(sysUser1);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //退出系统
    @ApiOperation(value = "用户退出")
    @GetMapping("/quit")
    public ResultJson quit() {
        try {
            //退出系统,删除session
            HttpServletRequest request = ((ServletRequestAttributes)
                    RequestContextHolder.getRequestAttributes())
                    .getRequest();
            HttpSession session = request.getSession();
            session.removeAttribute("loginUser");
            return ResultJson.success("退出成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //重置密码
    @ApiOperation(value = "重置密码", notes = "重置密码")
    @GetMapping(value = "/resetPsw")
    public ResultJson resetPsw(long id) {
        //重置默认密码
        String passwoord = "123456";
        try {
            //取到要修改的用户
            SysUser sysUser = iSysUserService.getById(id);
            sysUser.setPassword(MD5.md5(passwoord));
            iSysUserService.updateById(sysUser);
            return ResultJson.success("重置成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //重置选中用户的密码
    @ApiOperation(value = "重置选中密码", notes = "重置密码")
    @PostMapping(value = "/resetCheckPsw")
    public ResultJson resetCheckPsw(@RequestBody Long[] userIdList) {
        //重置默认密码
        String passwoord = "123456";
        try {
            //取得要重置密码的用户
            for (int i = 0; i < userIdList.length; i++) {
                SysUser sysUser = new SysUser();
                sysUser = iSysUserService.getById(userIdList[i]);
                sysUser.setPassword(MD5.md5(passwoord));
                iSysUserService.updateById(sysUser);
            }
            return ResultJson.success("重置成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //判断账号是否存在
    @ApiOperation(value = "账号是否存在", notes = "用户登录时,异步验证输入的账号是否存在")
    @GetMapping(value = "/ifAccount")
    public ResultJson ifAccount(long id) {
        //重置默认密码
        String passwoord = "123456";
        try {
            //取到要修改的用户
            SysUser sysUser = iSysUserService.getById(id);
            sysUser.setPassword(MD5.md5(passwoord));
            iSysUserService.updateById(sysUser);
            return ResultJson.success("重置成功");
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }

    //用户修改密码
    @ApiOperation(value = "用户修改密码", notes = "用户登录时,异步验证输入的账号是否存在")
    @GetMapping(value = "/updatePsw")
    public ResultJson updatePsw(String oldPsw, String newPsw, long id) {
        try {
            SysUser sysUser = iSysUserService.getById(id);
            //先判断是否和原密码一致
            if (MD5.md5(oldPsw).equals(sysUser.getPassword())) {
                sysUser.setPassword(MD5.md5(newPsw));
                iSysUserService.updateById(sysUser);
                return ResultJson.success("修改成功");
            } else {
                return ResultJson.error(CodeMsg.OLDPSW_ERROR);
            }
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }
    //修改用户名称
    @ApiOperation(value = "用户修改名称", notes = "用户登录时,异步验证输入的账号是否存在")
    @GetMapping(value = "/updateName")
    public ResultJson updateName(String name, long id) {
        try {
            SysUser sysUser = iSysUserService.getById(id);
            //先判断是否和原密码一致
            sysUser.setName(name);
            iSysUserService.updateById(sysUser);
            return ResultJson.success(sysUser);
        } catch (Exception e) {
            return ResultJson.error(CodeMsg.SERVER_ERROR);
        }
    }
}

